package com.cxyjy.common.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * 请求相关的工具类
 */
public class JRequestUtil {
    /**
     * 发送常规post请求
     *
     * @param url
     * @param postData
     * @param contentType
     * @return
     * @throws IOException
     */
    public static Object sendPostRequest(URL url, String postData, String contentType) throws IOException {
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        // 设置通用的请求属性
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", contentType);
        conn.setRequestProperty("connection", "Keep-Alive");
        conn.setRequestProperty("User-Agent", "PostmanRuntime/7.42.0");
        conn.setRequestProperty("Accept-Encoding", "gzip, deflate, br");
        // 发送POST请求必须设置如下两行
        conn.setDoOutput(true);
        conn.setDoInput(true);
        try{
            OutputStream os = conn.getOutputStream();
            byte[] input = postData.getBytes(StandardCharsets.UTF_8);
            os.write(input);
            os.flush();
            os.close();
        }catch (ConnectException e){
            throw new ConnectException("与Comfy UI的连接出现问题");
        }
        //获取响应
        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        String inputLine = "";
        StringBuilder response = new StringBuilder();
        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();
        return JSONObject.parse(JObjectUtil.stringValue(response));
    }

    /**
     * 发送常规post请求
     *
     * @param url
     * @param postData
     * @return post请求返回
     * @throws IOException
     */
    public static Object sendPostRequest(URL url, String postData) throws IOException {
        return sendPostRequest(url, postData, "x-www-form-urlencoded");
    }


    /**
     * 常规发送get请求
     *
     * @param baseUrl   基础url
     * @param paramsMap get请求参数组成的Map，里面的字段会与基础url连接并通过拼接形成url。
     * @return
     * @throws IOException
     */
    public static Object sendGetRequest(URL baseUrl, Map<String, Object> paramsMap) throws IOException {
        String outputFilePath = "";
        URL url = createGetRequestURL(baseUrl, paramsMap);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        // 设置请求类型为GET
        conn.setRequestMethod("GET");
        int responseCode;
        // 3. 检查响应码
        try{
            responseCode = conn.getResponseCode();
        }catch(ConnectException e){
            throw new ConnectException("与Comfy UI的连接出现问题");
        }
//        System.out.println("Response Code : " + responseCode);
        if(responseCode != 200){
            return null;
        }
        if (conn.getContentType().contains("application/json")) {
            // 读取响应
            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String inputLine;
            StringBuilder response = new StringBuilder();
            while (JObjectUtil.isNotEmpty(inputLine = in.readLine())) {
                response.append(inputLine);
            }
            in.close();
            if(JObjectUtil.toMap(JSON.parse(JObjectUtil.stringValue(response))).isEmpty()){
                return null;
            }
            return JSON.parse(JObjectUtil.stringValue(response));
        } else if (conn.getContentType().contains("video/mp4")) {
            //下载视频文件
            try {
                String outputPathStr;
//                outputPathStr = System.getProperty("user.dir")+"/src/main/resources/static/video/";
                /**
                 * getUsersDownloadFolderPath()获取用户当前系统的download文件夹路径，写了win、mac、linux、unix的
                 */
                outputPathStr = JPathUtil.getUsersDownloadFolderPath();
                if(JObjectUtil.isEmpty(outputPathStr)){
                    return null;
                }
                outputFilePath = outputPathStr + paramsMap.get("filename") ;
                File ops = new File(outputPathStr);
                //没有路径就创建路径
                if (!ops.exists()) {
                    ops.mkdirs();
                }
                //获取输入流
                InputStream inputStream = conn.getInputStream();
                //创建文件输出流
                FileOutputStream fileOutputStream = new FileOutputStream(outputFilePath);
                //创建缓冲区
                byte[] buffer = new byte[4096];
                int bytesRead;
                //读取文件输入流并写入文件输出流
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    fileOutputStream.write(buffer, 0, bytesRead);
                }
                // 8. 关闭流
                fileOutputStream.close();
                inputStream.close();
                System.out.println("视频下载完成: " + outputFilePath);
                return outputFilePath;
            } catch (IOException e) {
                e.printStackTrace();
            }

        } else if (conn.getContentType().contains("image/png")) {
            InputStream inputStream = conn.getInputStream();
            FileOutputStream outputStream = new FileOutputStream("received_image.jpg"); // 保存图片的路径
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        }

        return null;
    }

    /**
     * 根据baseUrl和接口参数生成完整的get请求url
     * 如果参数为null则直接返回baseUrl
     *
     * @param baseUrl   get请求不带参数的Url
     * @param paramsMap get请求参数
     * @return
     */
    public static URL createGetRequestURL(URL baseUrl, Map<String, Object> paramsMap) throws MalformedURLException {
        if (paramsMap == null || paramsMap.isEmpty()) {
            return baseUrl;
        }
        StringBuilder urlBuilder = new StringBuilder();
        for (Map.Entry<String, Object> entry : paramsMap.entrySet()) {
            if (JObjectUtil.isNotEmpty(entry.getValue()))
                urlBuilder.append('&').append(entry.getKey()).append('=').append(JRequestUtil.encode(entry.getValue()));
        }
        if (urlBuilder.length() > 0 && urlBuilder.charAt(0) == '&') {
            urlBuilder.deleteCharAt(0);
        }
        urlBuilder.insert(0, JObjectUtil.stringValue(baseUrl) + "?");
        return new URL(JObjectUtil.stringValue(urlBuilder));
    }

    /**
     * 传参转换为utf-8编码
     *
     * @param urlString
     * @return
     */
    public static String encode(String urlString) {
        try {
            return URLEncoder.encode(urlString, "UTF-8");

        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("Unsupported encode", e);
        }
    }

    public static String encode(Object obj) {
        return encode(JObjectUtil.stringValue(obj));
    }

    // 内网地址可达性检测
    public static boolean isServerReachable() {
        String osName = System.getProperty("os.name").toLowerCase();
        if(osName.contains("mac")){
            return false;
        }else{
            return true;
        }
    }

    // 地址选择逻辑 内网（服务器）不通就用localhost（证明本地在测试）
    public static String detectComfyUIHost() {
        return isServerReachable() ? "192.168.88.8:18501" : "localhost:18501";
    }

    private static byte[] readFully(InputStream inputStream) throws IOException {
        byte[] buffer = new byte[4096]; // 初始缓冲区大小
        int bytesRead = 0;
        int offset = 0;
        // 使用循环读取直到没有更多数据
        while ((bytesRead = inputStream.read(buffer, offset, 4096)) != -1) {
            offset += bytesRead;
            // 如果已经读满缓冲区，则需要增加缓冲区大小
            if (offset == buffer.length) {
                byte[] newBuffer = new byte[buffer.length * 2];
                System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
                buffer = newBuffer;
            }
        }
        // 如果缓冲区大小大于实际读取的数据，则需要创建一个新的数组来减少内存消耗
        if (offset < buffer.length) {
            byte[] trimmedBuffer = new byte[offset];
            System.arraycopy(buffer, 0, trimmedBuffer, 0, offset);
            return trimmedBuffer;
        }
        return buffer;
    }


}

